package com.devenv.service;

import com.devenv.entity.SoftwareVersion;
import com.devenv.repository.SoftwareVersionRepository;
import com.devenv.dto.SoftwareVersionDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

/**
 * 软件版本服务实现
 * <p>
 * 提供软件版本的完整管理功能，包括版本发布、下载统计、版本检查等
 * </p>
 * 
 * @author DevEnv OpenSource Team
 * @version 1.0.0
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SoftwareVersionService {

    private final SoftwareVersionRepository softwareVersionRepository;

    /**
     * 根据ID查询软件版本
     */
    @Cacheable(value = "softwareVersion", key = "#id")
    public Optional<SoftwareVersion> findById(Long id) {
        log.debug("查询软件版本，ID: {}", id);
        return softwareVersionRepository.findById(id);
    }

    /**
     * 根据软件ID查询所有版本
     */
    @Cacheable(value = "softwareVersions", key = "#softwareId")
    public List<SoftwareVersion> findBySoftwareId(Long softwareId) {
        log.debug("查询软件的所有版本，软件ID: {}", softwareId);
        return softwareVersionRepository.findBySoftwareIdOrderByReleaseDateDesc(softwareId);
    }

    /**
     * 根据软件ID查询可用版本
     */
    @Cacheable(value = "availableVersions", key = "#softwareId")
    public List<SoftwareVersion> findAvailableVersions(Long softwareId) {
        log.debug("查询软件的可用版本，软件ID: {}", softwareId);
        return softwareVersionRepository.findBySoftwareIdAndStatusOrderByReleaseDateDesc(
                softwareId, "ACTIVE");
    }

    /**
     * 获取软件的最新版本
     */
    @Cacheable(value = "latestVersion", key = "#softwareId")
    public Optional<SoftwareVersion> getLatestVersion(Long softwareId) {
        log.debug("获取软件最新版本，软件ID: {}", softwareId);
        return softwareVersionRepository.findBySoftwareIdAndIsLatestTrue(softwareId);
    }

    /**
     * 根据软件ID和版本号查询
     */
    @Cacheable(value = "softwareVersionByNumber", key = "#softwareId + ':' + #version")
    public Optional<SoftwareVersion> findByVersion(Long softwareId, String version) {
        log.debug("根据版本号查询软件版本，软件ID: {}, 版本: {}", softwareId, version);
        return softwareVersionRepository.findBySoftwareIdAndVersion(softwareId, version);
    }

    /**
     * 分页查询软件版本
     */
    public Page<SoftwareVersion> findAll(Pageable pageable) {
        log.debug("分页查询软件版本，页码: {}, 大小: {}", pageable.getPageNumber(), pageable.getPageSize());
        return softwareVersionRepository.findAll(pageable);
    }

    /**
     * 根据状态查询版本
     */
    public Page<SoftwareVersion> findByStatus(String status, Pageable pageable) {
        log.debug("根据状态查询软件版本，状态: {}", status);
        return softwareVersionRepository.findByStatusOrderByReleaseDateDesc(status, pageable);
    }

    /**
     * 创建软件版本
     */
    @Transactional
    @CacheEvict(value = {"softwareVersions", "availableVersions", "latestVersion"}, key = "#dto.softwareId")
    public SoftwareVersion createVersion(SoftwareVersionDTO dto) {
        log.info("创建软件版本，软件ID: {}, 版本: {}", dto.getSoftwareId(), dto.getVersion());
        
        // 检查版本是否已存在
        if (softwareVersionRepository.findBySoftwareIdAndVersion(dto.getSoftwareId(), dto.getVersion()).isPresent()) {
            throw new IllegalArgumentException("软件版本已存在: " + dto.getVersion());
        }

        SoftwareVersion version = new SoftwareVersion();
        version.setSoftwareId(dto.getSoftwareId());
        version.setVersion(dto.getVersion());
        version.setReleaseDate(dto.getReleaseDate() != null ? dto.getReleaseDate() : LocalDate.now());
        version.setDownloadPath(dto.getDownloadPath());
        version.setFileSize(dto.getFileSize());
        version.setChangelog(dto.getChangelog());
        version.setSystemRequirements(dto.getSystemRequirements());
        version.setStatus(dto.getStatus() != null ? dto.getStatus() : "ACTIVE");
        version.setDownloadCount(0L);
        version.setChecksumMd5(dto.getChecksumMd5());
        version.setChecksumSha256(dto.getChecksumSha256());
        version.setIsLatest(false); // 默认不是最新版本

        SoftwareVersion savedVersion = softwareVersionRepository.save(version);

        // 如果标记为最新版本，更新其他版本的最新标记
        if (Boolean.TRUE.equals(dto.getIsLatest())) {
            setAsLatestVersion(savedVersion.getId());
        }

        return savedVersion;
    }

    /**
     * 更新软件版本
     */
    @Transactional
    @Caching(
        put = {@CachePut(value = "softwareVersion", key = "#id")},
        evict = {
            @CacheEvict(value = {"softwareVersions", "availableVersions", "latestVersion"}, allEntries = true)
        }
    )
    public SoftwareVersion updateVersion(Long id, SoftwareVersionDTO dto) {
        log.info("更新软件版本，ID: {}", id);
        
        SoftwareVersion version = softwareVersionRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("软件版本不存在，ID: " + id));

        version.setReleaseDate(dto.getReleaseDate());
        version.setDownloadPath(dto.getDownloadPath());
        version.setFileSize(dto.getFileSize());
        version.setChangelog(dto.getChangelog());
        version.setSystemRequirements(dto.getSystemRequirements());
        version.setStatus(dto.getStatus());
        version.setChecksumMd5(dto.getChecksumMd5());
        version.setChecksumSha256(dto.getChecksumSha256());

        SoftwareVersion savedVersion = softwareVersionRepository.save(version);

        // 如果标记为最新版本，更新其他版本的最新标记
        if (Boolean.TRUE.equals(dto.getIsLatest()) && !version.getIsLatest()) {
            setAsLatestVersion(id);
        }

        return savedVersion;
    }

    /**
     * 设置为最新版本
     */
    @Transactional
    @CacheEvict(value = {"latestVersion", "softwareVersions", "availableVersions"}, allEntries = true)
    public void setAsLatestVersion(Long versionId) {
        log.info("设置最新版本，版本ID: {}", versionId);
        
        SoftwareVersion version = softwareVersionRepository.findById(versionId)
                .orElseThrow(() -> new IllegalArgumentException("软件版本不存在，ID: " + versionId));

        // 取消该软件的所有版本的最新标记
        softwareVersionRepository.clearLatestVersionBySoftwareId(version.getSoftwareId());
        
        // 设置当前版本为最新
        version.setIsLatest(true);
        softwareVersionRepository.save(version);
    }

    /**
     * 增加下载次数
     */
    @Transactional
    @CachePut(value = "softwareVersion", key = "#versionId")
    public SoftwareVersion incrementDownloadCount(Long versionId) {
        log.debug("增加下载次数，版本ID: {}", versionId);
        
        SoftwareVersion version = softwareVersionRepository.findById(versionId)
                .orElseThrow(() -> new IllegalArgumentException("软件版本不存在，ID: " + versionId));

        version.setDownloadCount(version.getDownloadCount() + 1);
        return softwareVersionRepository.save(version);
    }

    /**
     * 批量更新版本状态
     */
    @Transactional
    @CacheEvict(value = {"softwareVersions", "availableVersions"}, allEntries = true)
    public void updateVersionStatus(List<Long> versionIds, String status) {
        log.info("批量更新版本状态，版本数量: {}, 状态: {}", versionIds.size(), status);
        
        List<SoftwareVersion> versions = softwareVersionRepository.findAllById(versionIds);
        versions.forEach(version -> version.setStatus(status));
        softwareVersionRepository.saveAll(versions);
    }

    /**
     * 删除软件版本
     */
    @Transactional
    @Caching(
        evict = {
            @CacheEvict(value = "softwareVersion", key = "#id"),
            @CacheEvict(value = {"softwareVersions", "availableVersions", "latestVersion"}, allEntries = true)
        }
    )
    public boolean deleteVersion(Long id) {
        log.info("删除软件版本，ID: {}", id);
        
        Optional<SoftwareVersion> versionOpt = softwareVersionRepository.findById(id);
        if (versionOpt.isPresent()) {
            SoftwareVersion version = versionOpt.get();
            
            // 如果是最新版本，需要重新设置最新版本
            if (version.getIsLatest()) {
                // 查找同软件的其他活跃版本
                List<SoftwareVersion> otherVersions = softwareVersionRepository
                        .findBySoftwareIdAndStatusAndIdNotOrderByReleaseDateDesc(
                                version.getSoftwareId(), "ACTIVE", id);
                
                if (!otherVersions.isEmpty()) {
                    // 设置最新的其他版本为最新版本
                    SoftwareVersion newLatest = otherVersions.get(0);
                    newLatest.setIsLatest(true);
                    softwareVersionRepository.save(newLatest);
                }
            }
            
            softwareVersionRepository.deleteById(id);
            return true;
        }
        return false;
    }

    /**
     * 获取版本统计信息
     */
    @Cacheable(value = "versionStats", key = "#softwareId")
    public VersionStats getVersionStats(Long softwareId) {
        log.debug("获取版本统计信息，软件ID: {}", softwareId);
        
        List<SoftwareVersion> versions = findBySoftwareId(softwareId);
        
        long totalDownloads = versions.stream()
                .mapToLong(SoftwareVersion::getDownloadCount)
                .sum();
        
        long activeVersions = versions.stream()
                .filter(v -> "ACTIVE".equals(v.getStatus()))
                .count();
        
        long betaVersions = versions.stream()
                .filter(v -> "BETA".equals(v.getStatus()) || "ALPHA".equals(v.getStatus()))
                .count();
        
        return new VersionStats(versions.size(), (int)activeVersions, (int)betaVersions, totalDownloads);
    }

    /**
     * 检查版本兼容性
     */
    public boolean isVersionCompatible(Long versionId, String systemInfo) {
        log.debug("检查版本兼容性，版本ID: {}", versionId);
        
        Optional<SoftwareVersion> versionOpt = findById(versionId);
        if (versionOpt.isEmpty()) {
            return false;
        }
        
        SoftwareVersion version = versionOpt.get();
        String requirements = version.getSystemRequirements();
        
        // 这里可以实现更复杂的兼容性检查逻辑
        // 目前只做简单的字符串包含检查
        if (requirements == null || systemInfo == null) {
            return true; // 没有要求信息时默认兼容
        }
        
        return requirements.toLowerCase().contains(systemInfo.toLowerCase());
    }

    /**
     * 版本统计信息类
     */
    public static class VersionStats {
        private final int totalVersions;
        private final int activeVersions;
        private final int betaVersions;
        private final long totalDownloads;

        public VersionStats(int totalVersions, int activeVersions, int betaVersions, long totalDownloads) {
            this.totalVersions = totalVersions;
            this.activeVersions = activeVersions;
            this.betaVersions = betaVersions;
            this.totalDownloads = totalDownloads;
        }

        public int getTotalVersions() { return totalVersions; }
        public int getActiveVersions() { return activeVersions; }
        public int getBetaVersions() { return betaVersions; }
        public long getTotalDownloads() { return totalDownloads; }
    }
}
